<?php

/**
 * User: day
 * Date: 2018/10/9
 * Time: 10:52
 * Desc: 
 */

namespace App\Console\Commands\ReportData;

use App\Console\Base;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Carbon;
use common\utils\SysCode;

abstract class BaseReport extends Base
{

    public $reportName = "";
    public $redisTimeKey = "";

    /**
     * 处理程序
     * @param $reload 是否需要重新加载当天数据的标志（防错机制）
     */
    public function handle()
    {
        if (empty($this->reportName)) {
            return error_exit(SysCode::INTERNAL_SERVER_ERROR, "未定义有效模块名");
        }
        $this->redisTimeKey = "reportKeys:" . $this->reportName;
        $reload = $this->option('reload');
        $begin = $this->option('begin');
        $end = $this->option('end');
        $command = $this->option('command');
        if ($command) {
            switch ($command) {
                case 'today':
                    $begin = Carbon::today();           // 00:00:00
                    $end = Carbon::today()->endOfDay(); // 23:59:59
                    break;
                case 'yesterday':
                    $begin = Carbon::yesterday();            // 00:00:00
                    $end = Carbon::yesterday()->endOfDay(); // 23:59:59
                    break;
            }
        } elseif ($reload) {
            if (empty($begin) || empty($end)) {
                $this->error("重新加载数据必须带上时间范围, eg: begin=2018-10-10 end=2018-10-11");
                return;
            }
            $begin = Carbon::parse($begin);           // 00:00:00
            $end = Carbon::parse($end)->endOfDay();  // 23:59:59
        }
        $curTime = Carbon::now();
        $data = [];
        // 获取数据
        // 如果是重新加载，则按天重新读取数据
        if ($reload) {
            $this->info("拉取区间开始时间：" . $begin);
            if ($this->reportName == "ReportAgent"){
                $data = $this->getData($begin, $end);
            }else{
                // 一天一天的拉
                while ($begin < $end) {
                    // 获取数据
                    $dayEnd = $begin->copy()->endOfDay();;
                    $data = array_merge($data, $this->getData($begin, $dayEnd));
                    $begin = $begin->addDay(1);
                }
            }
            $this->info("拉取区间结束时间：" . $end);
        } else {
            $lastTime = $this->getTimeFromRedis($this->redisTimeKey);
            $this->info("拉取开始时间：" . $lastTime);
            // 获取数据
            $data = $this->getData($lastTime, $curTime);
            $this->info("拉取结束时间：" . $curTime);
        }
        // 处理数据
        $res = $this->dealData($data);
        if (!$res) {
            $this->error("数据保存失败！");
            return;
        }
        // 保存成功，更新最后拉取时间
        $redis = Redis::connection();
        $redis->set($this->redisTimeKey, $curTime);
    }

    /**
     * 获取需要处理的数据
     */
    abstract public function getData($beginTime, $endTime);
    /**
     * 处理数据
     */
    abstract public function dealData($data);
    /**
     * 安全获取 redis key 的值
     */
    public function getTimeFromRedis($timeKey)
    {
        // 初始化 redis 记录的值
        $redis = Redis::connection();
        if (!$redis->exists($timeKey)) {
            $curTime = Carbon::now();
            $redis->set($timeKey, $curTime);
            $this->error("初始化 redis 数据：{$timeKey} -> {$curTime}");
        }
        $time = $redis->get($timeKey);

        if ($time === false) {
            $msg = "获取 redis 失败！key: {$timeKey}";
            $this->error($msg);
            return error_exit(SysCode::INTERNAL_SERVER_ERROR, $msg);
        }

        return Carbon::parse($time);
    }
}